import functools

from coin.exchange.base.kr_rest.product import NativeProduct, NormProduct
from coin.exchange.upbit_v1.kr_rest.constants import (active_currency_list,
                                                      coin_list,
                                                      fiat_list)
from coin.exchange.upbit_v1.kr_rest.currency import UpbitCurrency


@functools.lru_cache(maxsize=1)
def get_active_symbol_list():
  res = []
  for base in active_currency_list:
    for quote in fiat_list:
      if base != quote:
        product = UpbitProduct.FromStrPair(base, quote)
        res.append(product.native_symbol)
  return res


class UpbitProduct(NativeProduct):
  _exchange = "Upbit"
  NativeCurrencyType = UpbitCurrency

  def __init__(self, base, quote):
    native_symbol = "%s-%s" % (quote.native_currency, base.native_currency)
    NativeProduct.__init__(self, base, quote, native_symbol)
    self.native_symbol_crix = "CRIX.UPBIT." + native_symbol

  @classmethod
  def FromProduct(cls, product):
    assert isinstance(product, NormProduct), type(product)
    base = UpbitCurrency.FromCurrency(product.base)
    quote = UpbitCurrency.FromCurrency(product.quote)
    return UpbitProduct(base, quote)

  @classmethod
  def FromStrProductImpl(cls, product, current_datetime):
    assert type(product) == str
    assert "-" in product
    ret = product.split("-")
    assert len(ret) == 2
    base = UpbitCurrency.FromStrCurrency(ret[0], current_datetime)
    quote = UpbitCurrency.FromStrCurrency(ret[1], current_datetime)
    assert base.currency != 'KRW'
    return UpbitProduct(base, quote)

  @classmethod
  def FromStrNativeProductImpl(cls, product, current_datetime):
    if product.startswith('CRIX.UPBIT.'):
      product = product.replace('CRIX.UPBIT.', '')
    if "-" in product:
      ret = product.split("-")
      assert len(ret) == 2
      quote = UpbitCurrency.FromStrNativeCurrency(ret[0], current_datetime)
      base = UpbitCurrency.FromStrNativeCurrency(ret[1], current_datetime)
      return UpbitProduct(base, quote)
    else:
      base = UpbitCurrency.FromStrNativeCurrency(product, current_datetime)
      quote = UpbitCurrency.FromStrNativeCurrency('KRW', current_datetime)
      return UpbitProduct(base, quote)

  @staticmethod
  def FromNativeCrixStr(product_crix_str):
    assert type(product_crix_str) == str
    exploded = product_crix_str.split('.')
    assert len(exploded) == 3
    assert exploded[0] == 'CRIX' and exploded[1] == 'UPBIT'
    quote, base = exploded[2].split('-')
    base = UpbitCurrency.FromStrNativeCurrency(base)
    quote = UpbitCurrency.FromStrNativeCurrency(quote)
    return UpbitProduct(base, quote)


def get_upbit_product_list():
  return [UpbitProduct.FromStr('%s-%s' % (coin, fiat)) for fiat in fiat_list for coin in coin_list]
